Skip to content

Meshplot Tutorials

Meshplot is a simple, and fast 2d and 3d mesh viewer based on pythreejs.

Downloading Meshplot

Meshplot can be downloaded from Conda forge.

To start using libigl you just need to import it together with the numpy.

import numpy as np
import meshplot as mp

Mesh representation

Meshplot uses numpy to encode vectors and matrices.

A triangular mesh is encoded as a pair of matrices:

v: np.array
f: np.array

data = np.load('data.npz')
v, f, n, fs = data["v"], data["f"], data["n"], data["fs"]
v1, f1, v2, f2 = data["v1"], data["f1"], data["v2"], data["f2"]

Visualizing surfaces

This tutorial shows how to visualize surfaces, their properties and additional debugging information through the plot function. It can be used to visualize the previously loaded triangle mesh:

mp.plot(v, f)

Scalar field visualization

Colors and normals can be associated to faces or vertices using the same plot function with three parameters.

The key parameter c represents the vertex or face colors and can be one of the following:

  1. A #v by 1 vector with one function value per vertex, which gets normalized and converted into vertex color values using the viridis colormap.
  2. A #v by 3 vector with RGB color values per vertex. The color values should be in the range 0.0-1.0.
  3. A single color value for all vertices in the form of a numpy array [R, G, B] in the range 0.0-1.0.
  4. A #f by 1 vector with one function value per face, which gets normalized and converted into face color values using the viridis colormap.
  5. A #f by 3 vector with RGB color values per face. The color values should be in the range 0.0-1.0.

The following four examples show vertex function colors (in this case just the y-coordinate), vertex normals as colors per vertex, random colors per face and face function colors (in this case the size of the faces):

d = mp.subplot(v, f, c=v[:, 1], s=[2, 2, 0])
mp.subplot(v, f, c=n, s=[2, 2, 1], data=d)
mp.subplot(v, f, c=np.random.rand(*f.shape), s=[2, 2, 2], data=d)
mp.subplot(v, f, c=fs, s=[2, 2, 3], data=d)

Overlays, Textures and Shading

In addition to plotting the surface, the viewer supports the visualization of bounding boxes, points and lines. These overlays can be very helpful while developing geometric processing algorithms to plot debug information.

The following example draws a point of a given color for each row of v_box. The point is placed at the coordinates specified in each row of v_box, which is a #v_box by 3 matrix. In addition, edges of a given color are drawn for the vertices v_box with the indices f_box:

m = np.min(v, axis=0)
ma = np.max(v, axis=0)

# Corners of the bounding box
v_box = np.array([[m[0], m[1], m[2]], [ma[0], m[1], m[2]], [ma[0], ma[1], m[2]], [m[0], ma[1], m[2]],
                  [m[0], m[1], ma[2]], [ma[0], m[1], ma[2]], [ma[0], ma[1], ma[2]], [m[0], ma[1], ma[2]]])

# Edges of the bounding box
f_box = np.array([[0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6], [6, 7], 
                  [7, 4], [0, 4], [1, 5], [2, 6], [7, 3]], dtype=np.int)

p = mp.plot(v, f, return_plot=True)

p.add_edges(v_box, f_box, shading={"line_color": "red"})
p.add_points(v_box, shading={"point_color": "green"});

The viewer allows for many customization options, which are presented below:

mi = np.min(v, axis=0)
ma = np.max(v, axis=0)

shading = {"flat":True, # Flat or smooth shading of triangles
           "wireframe":False, "wire_width": 0.03, "wire_color": "black", # Wireframe rendering
           "width": 600, "height": 600, # Size of the viewer canvas
           "antialias": True, # Antialising, might not work on all GPUs
           "scale": 2.0, # Scaling of the model
           "side": "DoubleSide", # FrontSide, BackSide or DoubleSide rendering of the triangles
           "colormap": "viridis", "normalize": [None, None], # Colormap and normalization for colors
           "background": "#ffffff", # Background color of the canvas
           "line_width": 1.0, "line_color": "black", # Line properties of overlay lines
           "bbox": True, # Enable plotting of bounding box
           "point_color": "red", "point_size": 0.01 # Point properties of overlay points
          }

p = mp.plot(v, f, shading=shading, return_plot=True)

# Instead of adding edges in the form of (v, f), also lines of the form (start, end) can be added
p.add_lines(mi, ma, shading={"line_color": "red"}) 

# The vertex positions can be updated as well
v += 0.003 * np.random.rand(v.shape[0], v.shape[1])
# The plotted objects get increasing ids. In this case the mesh object has id 0, and the lines object id 1.
p.update_object(vertices=v)

Events and Widgets

The viewer supports to use interactive widgets from the ipywidgets package to manipulate the plot.

v = [v1, v2]
f = [f1, f2]
p = mp.plot(v1, f1, return_plot=True)

@mp.interact(mesh=[('bump', 0), ('fertility', 1)])
def ff(mesh):
    mp.plot(v[mesh], f[mesh], plot=p)